﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Text;

namespace UtilZ.Dotnet.Ex.Base
{
    /// <summary>
    /// 类型转换基类
    /// </summary>
    public abstract class TypeConverterAbs : ITypeConverter
    {

        /// <summary>
        /// 转换器类型
        /// </summary>
        protected readonly PrimitiveDataTypes _converterType;


        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="converterType">转换器类型</param>
        public TypeConverterAbs(PrimitiveDataTypes converterType)
        {
            this._converterType = converterType;
        }



        /// <summary>
        /// 转换器类型
        /// </summary>
        public PrimitiveDataTypes ConverterType
        {
            get { return _converterType; }
        }



        /// <summary>
        /// 将字符串转换为值类型数据,包括枚举
        /// </summary>
        /// <param name="options">类型转换选项参数</param>
        /// <param name="value">要转换的值</param>
        /// <returns>转换后的值</returns>
        public object ConvertTo(ITypeConverterOptions options, object value)
        {
            PrimitiveDataTypes valueType = TypeEx.GetPrimitiveDataType(value);

            if (valueType == PrimitiveDataTypes.EnumType && options == null)
            {
                throw new ArgumentNullException(nameof(options), "当原始数据类型为枚举时,转换选项必须指定枚举解析器类型");
            }

            if (options != null && options.Converter != null)
            {
                return options.Converter.ConvertTo(options, value, valueType);
            }
            else
            {
                return this.PrimitiveConvertTo(options, value, valueType);
            }
        }

        /// <summary>
        /// 将字符串转换为值类型数据,包括枚举
        /// </summary>
        /// <param name="options">类型转换选项参数</param>
        /// <param name="value">要转换的值</param>
        /// <param name="valueType">值类型</param>
        /// <returns>转换后的值</returns>
        protected abstract object PrimitiveConvertTo(ITypeConverterOptions options, object value, PrimitiveDataTypes valueType);





        /// <summary>
        /// 转换数据到
        /// </summary>
        /// <param name="options">类型转换选项参数</param>
        /// <param name="value">要转换的值</param>
        /// <param name="result">转换后的值,存放在object中,如果转换失败为目标类型的默认值</param>
        /// <returns>转换成功返回true,失败返回false</returns>
        public bool TryConvertTo(ITypeConverterOptions options, object value, out object result)
        {
            try
            {
                PrimitiveDataTypes valueType = TypeEx.GetPrimitiveDataType(value);

                if (valueType == PrimitiveDataTypes.EnumType && options == null)
                {
                    throw new ArgumentNullException(nameof(options), "当原始数据类型为枚举时,转换选项必须指定枚举解析器类型");
                }

                if (options != null && options.Converter != null)
                {
                    return options.Converter.TryConvertTo(options, value, valueType, out result);
                }
                else
                {
                    return this.PrimitiveTryConvertTo(options, value, valueType, out result);
                }
            }
            catch (Exception ex)
            {
                ZLog.ZLoger.Warn(ex);
                result = null;
                return false;
            }
        }

        /// <summary>
        /// 转换数据到
        /// </summary>
        /// <param name="options">类型转换选项参数</param>
        /// <param name="value">要转换的值</param>
        /// <param name="valueType">值类型</param>
        /// <param name="result">转换后的值,存放在object中,如果转换失败为目标类型的默认值</param>
        /// <returns>转换成功返回true,失败返回false</returns>
        protected abstract bool PrimitiveTryConvertTo(ITypeConverterOptions options, object value, PrimitiveDataTypes valueType, out object result);


    }
}
